#ifndef XVARIABLETABLE_H
#define XVARIABLETABLE_H
#include <map>
#include <string>
#include <unordered_map>
#include <xscript/xitem.h>
#include <xscript/xerror.h>

using XScopedVarMap = std::map<std::wstring, std::shared_ptr<XItem>>;

struct XScopedBlock {
    uint32_t line;
    XScopedVarMap data;
    std::wstring name;
    std::shared_ptr<XScopedBlock> parent;
};

using XScopedBlockMap = std::map<uint32_t, std::shared_ptr<XScopedBlock>>;
using XVariableTableSet = std::unordered_map<std::wstring, std::shared_ptr<XScopedBlockMap>>;

class XVariableTable {
  public:
    XVariableTable();
  public:
    void printTable();

    bool setCurrentModule(const std::wstring& moduleName);
    std::shared_ptr<XScopedBlockMap> getCurrentModule()const;

    bool setCurrentBlock(uint32_t blockLine);
    std::shared_ptr<XScopedBlock> getCurrentBlock()const;

    XVariableTableSet::iterator addModule(const std::wstring& modulName);
    bool addBlock(const std::wstring& modulName, uint32_t blockLine, const std::wstring& blockName, std::shared_ptr<XScopedBlock> parent = nullptr);

    bool addVariable(const std::wstring& variable, std::shared_ptr<XItem> item);
    bool setVariable(const std::wstring& variable, std::shared_ptr<XItem> item);
    bool removeVariable(const std::wstring& varName);

    std::tuple<XItemPtr, uint32_t> getVariable(const std::wstring& varName);
  private:
    XVariableTableSet moduleSet;

    std::wstring currentModuleName;
    std::shared_ptr<XScopedBlockMap> currentModule;

    uint32_t currentBlockLine = ~0;
    std::shared_ptr<XScopedBlock> currentBlock;
};

#endif
